/**
 * 上海交大--鹏越惊虹
 */
package org.infosec.lc.exercises.callback;
import static java.lang.Math.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 作者：林超 <br>
 * 时间：2011-12-22 下午04:51:21 <br>
 * 完整类名：org.infosec.lc.exercises.callback.AnonymousBusinessTemplateExample2 <br>
 * 说明：一般内部接口比内部类用的更多。内部类中的方法可以有默认的实现。匿名内部类做为业务方法的参数传入时，会override默认的方法。内部接口的话，
 * 没有默认的实现。完全将具体的实现交给了匿名内部类。
 * 
 * 匿名内部类的思想是回调，即好茉坞原则。回调的一个好处是decouple。
 * 客户端只需要关心业务（比如匿名内部类的具体实现）而不用再关心一些资源的连接释放什么的
 * ，这些交给平台类中的模板方法。ruby的闭包还支持对数组中的每个元素，文件中的每行
 * ，结果集中的每个记录的操作。而用java实现这样的迭代并操作其中元素非常麻烦
 * 。感觉java中用的多的偏模板方法，即逻辑中固定一些流程，初始化及释放某些资源。<br>
 * <br>
 * 首先明确闭包的概念：一个代码段被用来做为方法的参数. java中没有直接使用某个方法做为另一个方法的参数的，java使用匿名内部类来模拟这种情况。
 * 
 * 匿名内部类往往是做为一个内部类（接口）的具体实现。在一些平台类（platform
 * class）中有一些模板方法。模板方法的包含了固定流程。其中某些步骤是调用了内部类
 * （接口）中的某些方法。但是平台类将这些方法的具体实现延迟到了业务类中。业务类调用平台类的模板方法，但是传入匿名内部类的实现做为模板方法的参数。
 * 
 * 注意：当类与接口(或者是接口与接口)发生方法命名冲突的时候，此时必须使用内部类来实现。 这是唯一一种必须使用内部类的情况。
 */
public class AnonymousBusinessTemplateExample2 {

	// 内部接口也是回调接口，只定义抽象方法。
	private interface Callback {
		Object doIt(Connection conn) throws SQLException;
		
		static class dd{
			void p(){
				System.out.println("XXXXXXXXXXXX");
			}
		}
	}
	private enum dX{
		s(1),d("ddd"),f(5){
			
			public Object xx(){
				System.out.println("XXFFFFFXX!");
				return f;
			}
		};
		private final Object value;
		public Object xx(){
			System.out.println("~~~~~~~~~~");
			return this.value;
		}
		
		dX(Object value){
			this.value=value;
		}

	}
	
	public static void main(String[] args) {
		
		System.out.println(abs(-20));
//		System.out.println(dX.s.xx());
//		System.out.println(dX.d.xx());
//		System.out.println(dX.f.xx());
	}

	// 模板方法（抽象）
	private Object execute(Callback callback) throws SQLException {
		Connection conn = openConnection();
		try {
			return callback.doIt(conn);
		} finally {
			closeConnection(conn);
		}
	}

	// 业务方法(具体)
	public Object sqlQuery(final String sql) throws SQLException {
		// 匿名内部类做为模板方法的参数来模拟闭包
		return execute(new Callback() {
			public Object doIt(Connection conn) throws SQLException {
				return conn.createStatement().executeQuery(sql);
			}
		});
	}

	public Connection openConnection() throws SQLException {
		return DriverManager.getConnection("", null);
	}

	public void closeConnection(Connection conn) throws SQLException {
		if (conn != null && !conn.isClosed()) {
			conn.close();
		}
	}
}
